package com.qf.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.qf.Constant.OrderConstant;
import com.qf.Constant.RabbitMqConstant;
import com.qf.Utils.ExecutorUtils;
import com.qf.dao.OrderDao;
import com.qf.entity.OrderDetailEntity;
import com.qf.entity.OrderEntity;
import com.qf.entity.StockParam;
import com.qf.excepotion.StockException;
import com.qf.excepotion.StockMsg;
import com.qf.feign.AddressService;
import com.qf.feign.CarService;
import com.qf.feign.StockService;
import com.qf.intercetor.DynamicDataSource;
import com.qf.service.OrderDetailService;
import com.qf.service.OrderService;
import com.qf.util.OrderUtil;
import com.qf.vo.Address;
import com.qf.vo.Car;
import com.qf.vo.OrderParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;


@Slf4j
@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
    @Autowired
    private CarService carService;
    @Autowired
    private AddressService addressService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderUtil orderUtil;
    @Autowired
    private DynamicDataSource dynamicDataSource;
    @Autowired
    private StockService stockService;
    @Autowired
    private OrderService orderService;
  @Autowired
  private RabbitTemplate rabbitTemplate;
    @Override
    @Transactional
    public String createOrder(OrderParam orderParam, Integer uid) throws ExecutionException, InterruptedException {
      //获取线程池
        ThreadPoolExecutor pool = ExecutorUtils.getExcutorsPool();
    //1.查询用户地址
        CompletableFuture<Address> futurn1 = CompletableFuture.supplyAsync(() -> {
            Address address = addressService.info(orderParam.getAddressId());
            return address;
        }, pool);
        //查询购物车
        CompletableFuture<Map<String, Object>> futurn2 = CompletableFuture.supplyAsync(() -> {
            //判断用户是否勾选支付
            Map<String, Object> carMap = null;
            if (!StringUtils.isEmpty(orderParam.getGid())) {
                List<String> asList = Arrays.asList(orderParam.getGid().split(","));
                carMap = carService.getCarListByUidAndGid(uid, asList);
            } else {
                carMap = carService.getCarListByUid(uid);
            }
            List<Car> carList = null;
            List<Map<String, Object>> list = (List<Map<String, Object>>) carMap.get("carList");
            BigDecimal totalPrice = BigDecimal.valueOf(Long.parseLong(carMap.get("totalPrice").toString()));
            carList = JSON.parseArray(JSON.toJSONString(list), Car.class);
            Map<String, Object> carObjectMap = new HashMap<>();
            carObjectMap.put("totalPrice", totalPrice);
            carObjectMap.put("carList", carList);
            return carObjectMap;
        }, pool);
        //3.组合地址和购物车任务
        CompletableFuture<Void> future = CompletableFuture.allOf(futurn1, futurn2);
        Void aVoid = future.get();//阻塞
        //4.扣减库存
        CompletableFuture<String> orderFuturn = CompletableFuture.supplyAsync(() -> {
            Map<String, Object> map = null;
            try {
                map = futurn2.get();
                List<Car> carList = (List<Car>) map.get("carList");
                List<StockParam> stockParamList = new ArrayList<>();
                for (Car car : carList) {
                    StockParam stockParam = new StockParam(car.getGid(), car.getSum(), 1);
                    stockParamList.add(stockParam);
                }
                return stockService.lockStock(stockParamList);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            return false;
        }, pool)//创建订单和订单详情
                .thenApplyAsync((falg) -> {
            if (falg) {
                // 先获取之前计算好的数据
                String oid = orderUtil.createOid(uid);
                Address address = null;
                Map<String, Object> map = null;
                try {
                    address = futurn1.get();
                    map = futurn2.get();
                List<Car> carList = (List<Car>) map.get("carList");
                BigDecimal totalPrice = (BigDecimal) map.get("totalPrice");
                OrderEntity order = new OrderEntity();
                order.setUid(uid);
                order.setName(address.getName());
                order.setAddress(address.getAddress());
                order.setPhone(address.getPhone());
                order.setPayType(1);
                order.setStatus(1);
                order.setTotalPrice(totalPrice);
                order.setCreateTime(new Date());
                order.setOid(oid);
                order.setSubject(carList.get(0).getGoods().getGname());
                order.setBody(carList.get(0).getGoods().getGdesc());
                log.debug("当前线程id" + Thread.currentThread().getId());
                Integer tabIndex = dynamicDataSource.getTabIndex();
                baseMapper.insert(order, tabIndex);
                //创建订单详情
                List<OrderDetailEntity> orderDetailEntityList = new ArrayList<>();
                for (Car car : carList) {
                    OrderDetailEntity orderDetail = new OrderDetailEntity();
                    orderDetail.setGname(car.getGoods().getGname());
                    orderDetail.setGid(car.getGid());
                    orderDetail.setGtype(car.getGoods().getGtypePid());
                    orderDetail.setGprice(car.getGoods().getGprice());
                    orderDetail.setGdesc(car.getGoods().getGdesc());
                    orderDetail.setGpng(car.getGoods().getGpng());
                    orderDetail.setOid(oid);
                    orderDetail.setSum(car.getSum());
                    orderDetail.setSubTotal(car.getSubTotal());
                    orderDetailEntityList.add(orderDetail);
                }
                log.debug("当前线程id" + Thread.currentThread().getId());
                orderDetailService.saveBatchOrderDetail(orderDetailEntityList, tabIndex);
                rabbitTemplate.convertAndSend(RabbitMqConstant.ORDER_EXCHANGE, "order.add", order);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
                return oid;
            } else {
                System.out.println("扣减库存失败。。");
                return null;
            }
        }, pool);
        String oid = orderFuturn.get();
        System.out.println("最后的oid:" + oid);
        if (StringUtils.isEmpty(oid)) {
            throw new StockException(StockMsg.UNLOCK_STOCK_ERROR);
        }
        return oid;
/*

        log.debug("当前线程id" + Thread.currentThread().getId());
        //判断用户是否勾选支付
        List<String> asList = Arrays.asList(orderParam.getGid().split(","));
        Map<String, Object> carMap = null;
        if (!StringUtils.isEmpty(orderParam.getGid())) {
            carMap = carService.getCarListByUidAndGid(uid, asList);
        } else {
            carMap = carService.getCarListByUid(uid);
        }
        //查询用户默认地址
        Integer def = 1;
        Address address = addressService.info(orderParam.getAddressId());
        List<Map<String, Object>> list = (List<Map<String, Object>>) carMap.get("carList");
        List<Car> carList = JSON.parseArray(JSON.toJSONString(list), Car.class);
        BigDecimal totalPrice = BigDecimal.valueOf(Long.parseLong(carMap.get("totalPrice").toString()));
        List<StockParam> stockParamList = new ArrayList<>();
        for (Car car : carList) {
            StockParam stockParam = new StockParam(car.getGid(), car.getSum(), 1);
            stockParamList.add(stockParam);
        }
        boolean lockStock = stockService.lockStock(stockParamList);
        if (!lockStock) {
            throw new StockException(StockMsg.UNLOCK_STOCK_ERROR);
        }
        String oid = orderUtil.createOid(uid);
        OrderEntity order = new OrderEntity();
        order.setUid(uid);
        order.setName(address.getName());
        order.setAddress(address.getAddress());
        order.setPhone(address.getPhone());
        order.setPayType(1);
        order.setStatus(1);
        order.setTotalPrice(totalPrice);
        order.setCreateTime(new Date());
        order.setOid(oid);
        order.setSubject(carList.get(0).getGoods().getGname());
        order.setBody(carList.get(0).getGoods().getGdesc());
        log.debug("当前线程id" + Thread.currentThread().getId());
        Integer tabIndex = dynamicDataSource.getTabIndex();
        baseMapper.insert(order, tabIndex);
        //创建订单详情
        List<OrderDetailEntity> orderDetailEntityList = new ArrayList<>();
        for (Car car : carList) {
            OrderDetailEntity orderDetail = new OrderDetailEntity();
            orderDetail.setGname(car.getGoods().getGname());
            orderDetail.setGid(car.getGid());
            orderDetail.setGtype(car.getGoods().getGtypePid());
            orderDetail.setGprice(car.getGoods().getGprice());
            orderDetail.setGdesc(car.getGoods().getGdesc());
            orderDetail.setGpng(car.getGoods().getGpng());
            orderDetail.setOid(oid);
            orderDetail.setSum(car.getSum());
            orderDetail.setSubTotal(car.getSubTotal());
            orderDetailEntityList.add(orderDetail);
        }
        log.debug("当前线程id" + Thread.currentThread().getId());
        orderDetailService.saveBatchOrderDetail(orderDetailEntityList, tabIndex);
        rabbitTemplate.convertAndSend(RabbitMqConstant.ORDER_EXCHANGE,"order.add",order);
*/


    }

    @Override
    public OrderEntity getById(String oid, Integer tabIndex) {
        OrderEntity orderEntity = baseMapper.selectById(oid, tabIndex);
        return orderEntity;
    }

    @Override
    public void updateOrderStatus(String oid, Integer status) {
        //设置数据源
        Integer uid=getLastUid(oid);
        int dbIndex=(uid% OrderConstant.ORDER_DB_SIZE)+1;
        DynamicDataSourceContextHolder.push(OrderConstant.ORDER_DB_PRE+dbIndex);
        //设置表的编号
        Integer tabIndex=(uid/OrderConstant.ORDER_DB_SIZE%OrderConstant.ORDER_TABLE_SIZE)+1;
         baseMapper.updateOrderStatus(oid,status,tabIndex);
    }

    @Override
    public OrderEntity getById2(String oid) {
        //设置数据源
        Integer uid=getLastUid(oid);
        int dbIndex=(uid% OrderConstant.ORDER_DB_SIZE)+1;
        DynamicDataSourceContextHolder.push(OrderConstant.ORDER_DB_PRE+dbIndex);
        //设置表的编号
        Integer tabIndex=(uid/OrderConstant.ORDER_DB_SIZE%OrderConstant.ORDER_TABLE_SIZE)+1;
        return baseMapper.selectById(oid,tabIndex);
    }

    @Override
    public OrderEntity getInfoById(String oid) {
        //设置数据源
        Integer uid=getLastUid(oid);
        int dbIndex=(uid% OrderConstant.ORDER_DB_SIZE)+1;
        DynamicDataSourceContextHolder.push(OrderConstant.ORDER_DB_PRE+dbIndex);
        //设置表的编号
        Integer tabIndex=(uid/OrderConstant.ORDER_DB_SIZE%OrderConstant.ORDER_TABLE_SIZE)+1;
        return baseMapper.getInfoById(oid,tabIndex);

    }

    private Integer getLastUid(String oid) {
        String substring = oid.substring(13, 13 + 4);
        return Integer.parseInt(substring);
    }

}